import Router from 'koa-router';
import { SysDictService } from '../../service/system/SysDict.js';
import {
  SysDict,
  CreateSysDictDto,
  UpdateSysDictDto,
  SysDictQueryDto,
  CreateSysDictDataDto,
  UpdateSysDictDataDto,
  SysDictDataQueryDto,
  BatchDeleteDto,
} from '../../entities/system/SysDict.js';
import { ValidationUtil } from '../../utils/validation.js';
import { Response } from '../../utils/response.js';
import type { AppContext } from '../../types/index.js';

class DictController {
  private static instance: DictController;
  private dictService: SysDictService;

  private constructor() {
    this.dictService = new SysDictService();
  }

  static getInstance(): DictController {
    if (!DictController.instance) {
      DictController.instance = new DictController();
    }
    return DictController.instance;
  }

  // 创建字典
  async createDict(ctx: AppContext): Promise<void> {
    try {
      const { dict_name, dict_key, dict_type, status, remark, is_sys } = ctx.request
        .body as CreateSysDictDto;

      // 参数验证
      if (!dict_name) {
        Response.validationError('字典名称不能为空');
        return;
      }
      if (!dict_key) {
        Response.validationError('字典标识不能为空');
        return;
      }
      if (typeof dict_type !== 'number') {
        Response.validationError('字典类型必须为数字');
        return;
      }

      // 检查字典标识是否已存在
      const existingDict = await this.dictService.getDictByKey(dict_key);
      if (existingDict) {
        Response.validationError('字典标识已存在');
        return;
      }

      const result = await this.dictService.createDict({
        dict_name,
        dict_key,
        dict_type,
        status: status ?? 0,
        remark: remark ?? '',
        is_sys: is_sys ?? 0,
      });

      Response.success('字典创建成功', result);
    } catch (error) {
      Response.serverError('字典创建失败: ' + (error as Error).message);
    }
  }

  // 获取字典列表
  async getDictList(ctx: AppContext): Promise<void> {
    try {
      const {
        page = 1,
        pageSize = 10,
        ...query
      } = ctx.query as SysDictQueryDto & { page?: string; pageSize?: string };

      const pageNum = parseInt(page.toString()) || 1;
      const size = parseInt(pageSize.toString()) || 10;

      const result = await this.dictService.getDictList(pageNum, size, query as Partial<SysDict>);
      Response.pagination('获取字典列表成功', result);
    } catch (error) {
      Response.serverError('获取字典列表失败: ' + (error as Error).message);
    }
  }

  // 更新字典
  async updateDict(ctx: AppContext): Promise<void> {
    try {
      const id = ValidationUtil.validateId(ctx.params.id, '字典ID');
      const updateData = ctx.request.body as UpdateSysDictDto;

      // 如果更新字典标识，检查是否已存在
      if (updateData.dict_key) {
        const existingDict = await this.dictService.getDictByKey(updateData.dict_key);
        if (existingDict && existingDict.id !== id) {
          Response.validationError('字典标识已存在');
          return;
        }
      }

      const result = await this.dictService.updateDict(id, updateData);
      if (result) {
        Response.success('字典更新成功');
      } else {
        Response.serverError('字典更新失败');
      }
    } catch (error) {
      Response.serverError('字典更新失败: ' + (error as Error).message);
    }
  }

  // 删除字典
  async deleteDict(ctx: AppContext): Promise<void> {
    try {
      const id = ValidationUtil.validateId(ctx.params.id, '字典ID');
      const result = await this.dictService.deleteDict(id);
      if (result) {
        Response.success('字典删除成功');
      } else {
        Response.serverError('字典删除失败');
      }
    } catch (error) {
      Response.serverError('字典删除失败: ' + (error as Error).message);
    }
  }

  // 批量删除字典
  async batchDeleteDict(ctx: AppContext): Promise<void> {
    try {
      const { ids } = ctx.request.body as BatchDeleteDto;
      if (!Array.isArray(ids) || ids.length === 0) {
        Response.validationError('请选择要删除的字典');
        return;
      }

      const result = await this.dictService.batchDeleteDict({ ids });
      if (result) {
        Response.success('批量删除字典成功');
      } else {
        Response.serverError('批量删除字典失败');
      }
    } catch (error) {
      Response.serverError('批量删除字典失败: ' + (error as Error).message);
    }
  }

  // 获取字典详情
  async getDictById(ctx: AppContext): Promise<void> {
    try {
      const id = ValidationUtil.validateId(ctx.params.id, '字典ID');
      const result = await this.dictService.getDictById(id);
      if (result) {
        Response.success('获取字典详情成功', result);
      } else {
        Response.notFound('字典不存在');
      }
    } catch (error) {
      Response.serverError('获取字典详情失败: ' + (error as Error).message);
    }
  }

  // 根据标识获取字典
  async getDictByKey(ctx: AppContext): Promise<void> {
    try {
      const { key } = ctx.params;
      if (!key) {
        Response.validationError('字典标识不能为空');
        return;
      }

      const result = await this.dictService.getDictByKey(key);
      if (result) {
        Response.success('获取字典成功', result);
      } else {
        Response.notFound('字典不存在');
      }
    } catch (error) {
      Response.serverError('获取字典失败: ' + (error as Error).message);
    }
  }

  // 创建字典数据
  async createDictData(ctx: AppContext): Promise<void> {
    try {
      const { name, value, dict_key, style, order, status, ext, remark, is_sys } = ctx.request
        .body as CreateSysDictDataDto;

      // 参数验证
      if (!name) {
        Response.validationError('字典数据名称不能为空');
        return;
      }
      if (!value) {
        Response.validationError('字典值不能为空');
        return;
      }
      if (!dict_key) {
        Response.validationError('字典标识不能为空');
        return;
      }

      // 检查字典是否存在
      const dict = await this.dictService.getDictByKey(dict_key);
      if (!dict) {
        Response.validationError('字典不存在');
        return;
      }

      const result = await this.dictService.createDictData({
        name,
        value,
        dict_key,
        style: style ?? '',
        order: order ?? 0,
        status: status ?? 0,
        ext: ext ?? '',
        remark: remark ?? '',
        is_sys: is_sys ?? 0,
      });

      Response.success('字典数据创建成功', result);
    } catch (error) {
      Response.serverError('字典数据创建失败: ' + (error as Error).message);
    }
  }

  // 获取字典数据列表
  async getDictDataList(ctx: AppContext): Promise<void> {
    try {
      const {
        page = 1,
        pageSize = 10,
        ...query
      } = ctx.query as SysDictDataQueryDto & { page?: string; pageSize?: string };

      const pageNum = parseInt(page.toString()) || 1;
      const size = parseInt(pageSize.toString()) || 10;

      const result = await this.dictService.getDictDataList(pageNum, size, query);
      Response.pagination('获取字典数据列表成功', result);
    } catch (error) {
      Response.serverError('获取字典数据列表失败: ' + (error as Error).message);
    }
  }

  // 根据字典标识获取字典数据
  async getDictDataByKey(ctx: AppContext): Promise<void> {
    try {
      const { key } = ctx.params;
      if (!key) {
        Response.validationError('字典标识不能为空');
        return;
      }

      const result = await this.dictService.getDictDataByKey(key);
      Response.success('获取字典数据成功', result);
    } catch (error) {
      Response.serverError('获取字典数据失败: ' + (error as Error).message);
    }
  }

  // 更新字典数据
  async updateDictData(ctx: AppContext): Promise<void> {
    try {
      const id = ValidationUtil.validateId(ctx.params.id, '字典数据ID');
      const updateData = ctx.request.body as UpdateSysDictDataDto;

      const result = await this.dictService.updateDictData(id, updateData);
      if (result) {
        Response.success('字典数据更新成功');
      } else {
        Response.serverError('字典数据更新失败');
      }
    } catch (error) {
      Response.serverError('字典数据更新失败: ' + (error as Error).message);
    }
  }

  // 删除字典数据
  async deleteDictData(ctx: AppContext): Promise<void> {
    try {
      const id = ValidationUtil.validateId(ctx.params.id, '字典数据ID');
      const result = await this.dictService.deleteDictData(id);
      if (result) {
        Response.success('字典数据删除成功');
      } else {
        Response.serverError('字典数据删除失败');
      }
    } catch (error) {
      Response.serverError('字典数据删除失败: ' + (error as Error).message);
    }
  }

  // 批量删除字典数据
  async batchDeleteDictData(ctx: AppContext): Promise<void> {
    try {
      const { ids } = ctx.request.body as BatchDeleteDto;
      if (!Array.isArray(ids) || ids.length === 0) {
        Response.validationError('请选择要删除的字典数据');
        return;
      }

      const result = await this.dictService.batchDeleteDictData({ ids });
      if (result) {
        Response.success('批量删除字典数据成功');
      } else {
        Response.serverError('批量删除字典数据失败');
      }
    } catch (error) {
      Response.serverError('批量删除字典数据失败: ' + (error as Error).message);
    }
  }

  // 获取字典数据详情
  async getDictDataById(ctx: AppContext): Promise<void> {
    try {
      const id = ValidationUtil.validateId(ctx.params.id, '字典数据ID');
      const result = await this.dictService.getDictDataById(id);
      if (result) {
        Response.success('获取字典数据详情成功', result);
      } else {
        Response.notFound('字典数据不存在');
      }
    } catch (error) {
      Response.serverError('获取字典数据详情失败: ' + (error as Error).message);
    }
  }
}

const router = new Router<Record<string, unknown>, AppContext>();
const dictController = DictController.getInstance();

// 字典路由
router.post('/system/dict', dictController.createDict.bind(dictController));
router.get('/system/dict', dictController.getDictList.bind(dictController));
router.put('/system/dict/:id', dictController.updateDict.bind(dictController));
router.delete('/system/dict/:id', dictController.deleteDict.bind(dictController));
router.delete('/system/dict/batch', dictController.batchDeleteDict.bind(dictController));
router.get('/system/dict/:id', dictController.getDictById.bind(dictController));
router.get('/system/dict/key/:key', dictController.getDictByKey.bind(dictController));

// 字典数据路由
router.post('/system/dict/data', dictController.createDictData.bind(dictController));
router.get('/system/dict/data', dictController.getDictDataList.bind(dictController));
router.get('/system/dict/data/key/:key', dictController.getDictDataByKey.bind(dictController));
router.put('/system/dict/data/:id', dictController.updateDictData.bind(dictController));
router.delete('/system/dict/data/:id', dictController.deleteDictData.bind(dictController));
router.delete('/system/dict/data/batch', dictController.batchDeleteDictData.bind(dictController));
router.get('/system/dict/data/:id', dictController.getDictDataById.bind(dictController));

export default router;
